import { CydonElement, define, watch } from 'cydon'
import { add, constants, getTerrain, getTile, map } from '../game'
import { buildings, mapSize, terrains } from '../defs'
import { queue } from './QTable'
import { Building, Recipe } from '../type'
import { recipeStr } from '../recipes'

/** 建筑物 */
const idToBuilding = new Map<number, Building>()
for (const b of buildings)
	idToBuilding.set(b.id, b)

/**
 * @element tile-info
 * 图块信息
 */
@define('tile-info')
export class TileInfo extends CydonElement {
	//#region 地形信息
	/** 地形 */
	get terrain() {
		return terrains[getTerrain(this.selected)] || ''
	}
	/** 植被 */
	get vegetation() {
		const tile = this.tile
		if ((tile[0] & 7) < 2) {
			const i = constants[tile[1] * 3]
			return i && terrains[i] || '无'
		}
		return '无'
	}
	/** 温度 */
	get temperature() {
		return (this.tile[1] & 15) * 2.5 - 10 + '℃'
	}
	/** 湿度 */
	get humidity() {
		return (this.tile[1] >> 4) * 6 + 5 + '%'
	}

	/** 原木产量 */
	get logCount() {
		const tile = this.tile
		if ((tile[0] & 7) < 2) {
			const i = constants[tile[1] * 3]
			return Math.max(0, i - 10)
		}
		return 0
	}
	/** 是否可挖掘 */
	get canDig() {
		const t = getTerrain(this.selected)
		return t == 0 || t == 1 || t == 5
	}
	/** 石头产量 */
	get stoneCount() {
		const t = getTerrain(this.selected)
		return t > 1 && t < 5 ? t - 1 : 0
	}
	//#endregion

	//#region 建筑信息
	/** 建筑物名称 */
	get name() {
		return this.level ? idToBuilding.get(this.tile[2])?.name : ''
	}
	/** 建筑物等级 */
	get level() {
		return this.tile[3] & 15
	}
	private _selectKind = false
	/** 选择同种建筑 */
	get selectKind() {
		return this._selectKind
	}
	set selectKind(value) {
		this._selectKind = value
		if (value)
			this.selectOther = false
	}
	private _selectOther = false
	/** 选择其他建筑 */
	get selectOther() {
		return this._selectOther
	}
	set selectOther(value) {
		this._selectOther = value
		if (value)
			this.selectKind = false
	}
	//#endregion

	/** 配方 */
	recipes: Recipe[] = []

	/** 选中的块号 */
	selected = -1

	/** 选中的图块 */
	tile!: Uint8Array

	connectedCallback() {
		watch(this, function (this: TileInfo) {
			this.data.tile = getTile(this.selected)
		})
		super.connectedCallback()
	}

	/** 升级 */
	upgrade() {
		const id = this.tile[2]
		if (this.selectKind) {
			for (let i = 0; i < mapSize; i++) {
				const level = map[i * 4 + 3] & 15
				if (level && map[i * 4 + 2] == id) {
					upgrade(id, level, i)
				}
			}
		}
		if (this.selectOther) {
			for (let i = 0; i < mapSize; i++) {
				const level = map[i * 4 + 3] & 15
				if (level && map[i * 4 + 2] != id) {
					upgrade(map[i * 4 + 2], level, i)
				}
			}
		}
		if (!this.selectKind && !this.selectOther)
			upgrade(id, this.level, this.selected)
	}

	/** 降级 */
	downgrade() {
		const id = this.tile[2]
		if (this.selectKind) {
			for (let i = 0; i < mapSize; i++) {
				const level = map[i * 4 + 3] & 15
				if (level && map[i * 4 + 2] == id) {
					downgrade(id, level, i)
				}
			}
		}
		if (this.selectOther) {
			for (let i = 0; i < mapSize; i++) {
				const level = map[i * 4 + 3] & 15
				if (level && map[i * 4 + 2] != id) {
					downgrade(map[i * 4 + 2], level, i)
				}
			}
		}
		if (!this.selectKind && !this.selectOther)
			downgrade(id, this.level, this.selected)
	}

	/** 拆除 */
	destroy() {
		const id = this.tile[2]
		if (this.selectKind) {
			for (let i = 0; i < mapSize; i++) {
				if (map[i * 4 + 2] == id) {
					destroy(id, i)
				}
			}
		}
		if (this.selectOther) {
			for (let i = 0; i < mapSize; i++) {
				if ((map[i * 4 + 3] & 15) &&
					map[i * 4 + 2] != id) {
					destroy(map[i * 4 + 2], i)
				}
			}
		}
		if (!this.selectKind && !this.selectOther)
			destroy(id, this.selected)
	}

	/** 砍树 */
	felling() {
		add('原木', this.logCount)
	}

	/** 挖掘 */
	dig() {
		const t = getTerrain(this.selected)
		add(t == 5 ? '沙子' : t ? '高岭土' : '黏土', 1)
	}

	/** 采石 */
	quarry() {
		add('石头', this.stoneCount)
	}
}

/** 升级 */
function upgrade(id: number, level: number, slot: number) {
	if (level >= 10)
		return
	const building = idToBuilding.get(id)!
	const k = 1 << level
	queue({
		name: '升级' + building.name,
		desc: '每秒消耗' + recipeStr(building.cost, k),
		slot,
		value: id | (level + 1) << 8,
		recipeId: building.recipeId!,
		k,
		remainTime: 3 + level,
	})
}

/** 降级 */
function downgrade(id: number, level: number, slot: number) {
	if (level < 2)
		return
	const building = idToBuilding.get(id)!
	const k = -level
	queue({
		name: '降级' + building.name,
		desc: '每秒获得' + recipeStr(building.cost, -k),
		slot,
		value: id | (level - 1) << 8,
		recipeId: building.recipeId!,
		k,
		remainTime: 2 + level,
	})
}

/** 拆除 */
function destroy(id: number, slot: number) {
	const building = idToBuilding.get(id)!
	queue({
		name: '拆除' + building.name,
		desc: '每秒获得' + recipeStr(building.cost, 1),
		slot,
		value: 0,
		recipeId: building.recipeId!,
		k: -1,
		remainTime: 1,
	})
}

declare global {
	interface HTMLElementTagNameMap {
		'tile-info': TileInfo
	}
}
